using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace PaulRz.Util.Threading
{
    /// <summary>
    /// This class provides helper methods for threading issues
    /// </summary>
    public static class ThreadUtils
    {
        public static readonly int NumberOfProcessors = Environment.ProcessorCount;
        
        private static bool IsSingleCPU = (Environment.ProcessorCount == 1);

        /// <summary>
        /// Thread.SpinWait customized function for correct support of single CPU.
        /// </summary>
        /// <param name="iterations">number of iterations of SpinWait</param>
        public static void SpinWait(int iterations)
        {
            if (!IsSingleCPU)
            {
                Thread.SpinWait(iterations);
            }
            else
            {
                for (int i = 0; i < iterations; ++i)
                    SwitchToThread();
            }
        }

        /// <summary>
        /// This function of kernel causes the calling thread to yield execution to another thread that is ready to run on the current processor.
        /// The operating system selects the thread to yield to.
        /// </summary>
        [DllImport("kernel32", ExactSpelling = true)]
        private static extern void SwitchToThread();
    }
}
